const logger = require('../config/logger');
const config = require('../config/config');

// 自定义错误类
class AppError extends Error {
  constructor(message, statusCode, code = null, details = null) {
    super(message);
    this.statusCode = statusCode;
    this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
    this.isOperational = true;
    this.code = code;
    this.details = details;
    
    Error.captureStackTrace(this, this.constructor);
  }
}

// 验证错误类
class ValidationError extends AppError {
  constructor(message, details = null) {
    super(message, 400, 'VALIDATION_ERROR', details);
  }
}

// 认证错误类
class AuthenticationError extends AppError {
  constructor(message = '认证失败') {
    super(message, 401, 'AUTHENTICATION_ERROR');
  }
}

// 授权错误类
class AuthorizationError extends AppError {
  constructor(message = '权限不足') {
    super(message, 403, 'AUTHORIZATION_ERROR');
  }
}

// 资源未找到错误类
class NotFoundError extends AppError {
  constructor(message = '资源未找到') {
    super(message, 404, 'NOT_FOUND_ERROR');
  }
}

// 冲突错误类
class ConflictError extends AppError {
  constructor(message = '资源冲突') {
    super(message, 409, 'CONFLICT_ERROR');
  }
}

// 速率限制错误类
class RateLimitError extends AppError {
  constructor(message = '请求过于频繁') {
    super(message, 429, 'RATE_LIMIT_ERROR');
  }
}

// 处理Sequelize错误
const handleSequelizeError = (err) => {
  let error;
  
  switch (err.name) {
    case 'SequelizeValidationError':
      const messages = err.errors.map(e => `${e.path}: ${e.message}`);
      error = new ValidationError('数据验证失败', {
        fields: err.errors.map(e => ({
          field: e.path,
          message: e.message,
          value: e.value
        }))
      });
      break;
      
    case 'SequelizeUniqueConstraintError':
      const field = err.errors[0]?.path || 'unknown';
      error = new ConflictError(`${field} 已存在`, {
        field,
        value: err.errors[0]?.value
      });
      break;
      
    case 'SequelizeForeignKeyConstraintError':
      error = new ValidationError('外键约束错误', {
        table: err.table,
        field: err.fields
      });
      break;
      
    case 'SequelizeConnectionError':
    case 'SequelizeConnectionRefusedError':
    case 'SequelizeHostNotFoundError':
    case 'SequelizeHostNotReachableError':
    case 'SequelizeInvalidConnectionError':
    case 'SequelizeConnectionTimedOutError':
      error = new AppError('数据库连接错误', 503, 'DATABASE_CONNECTION_ERROR');
      break;
      
    case 'SequelizeTimeoutError':
      error = new AppError('数据库操作超时', 504, 'DATABASE_TIMEOUT_ERROR');
      break;
      
    default:
      error = new AppError('数据库操作失败', 500, 'DATABASE_ERROR', {
        originalError: err.name
      });
  }
  
  return error;
};

// 处理JWT错误
const handleJWTError = (err) => {
  let error;
  
  switch (err.name) {
    case 'JsonWebTokenError':
      error = new AuthenticationError('无效的访问令牌');
      break;
      
    case 'TokenExpiredError':
      error = new AuthenticationError('访问令牌已过期');
      break;
      
    case 'NotBeforeError':
      error = new AuthenticationError('访问令牌尚未生效');
      break;
      
    default:
      error = new AuthenticationError('令牌验证失败');
  }
  
  return error;
};

// 处理Multer错误
const handleMulterError = (err) => {
  let error;
  
  switch (err.code) {
    case 'LIMIT_FILE_SIZE':
      error = new ValidationError('文件大小超出限制');
      break;
      
    case 'LIMIT_FILE_COUNT':
      error = new ValidationError('文件数量超出限制');
      break;
      
    case 'LIMIT_UNEXPECTED_FILE':
      error = new ValidationError('不支持的文件字段');
      break;
      
    case 'LIMIT_PART_COUNT':
      error = new ValidationError('表单字段过多');
      break;
      
    default:
      error = new ValidationError('文件上传失败');
  }
  
  return error;
};

// 处理MongoDB错误
const handleMongoError = (err) => {
  let error;
  
  if (err.code === 11000) {
    const field = Object.keys(err.keyValue)[0];
    error = new ConflictError(`${field} 已存在`);
  } else {
    error = new AppError('数据库操作失败', 500, 'DATABASE_ERROR');
  }
  
  return error;
};

// 处理Redis错误
const handleRedisError = (err) => {
  return new AppError('缓存服务错误', 503, 'CACHE_ERROR', {
    originalError: err.message
  });
};

// 发送错误响应
const sendErrorResponse = (err, req, res) => {
  const { statusCode, message, code, details } = err;
  
  // 构建错误响应
  const errorResponse = {
    success: false,
    error: {
      message,
      code: code || 'INTERNAL_ERROR',
      statusCode
    }
  };
  
  // 添加详细信息（仅在开发环境或验证错误时）
  if (config.env === 'development' || statusCode < 500) {
    if (details) {
      errorResponse.error.details = details;
    }
    
    if (config.env === 'development' && err.stack) {
      errorResponse.error.stack = err.stack;
    }
  }
  
  // 添加请求信息
  if (config.env === 'development') {
    errorResponse.error.request = {
      method: req.method,
      url: req.originalUrl,
      headers: req.headers,
      body: req.body,
      params: req.params,
      query: req.query
    };
  }
  
  // 添加时间戳和请求ID
  errorResponse.timestamp = new Date().toISOString();
  errorResponse.requestId = req.requestId;
  
  res.status(statusCode).json(errorResponse);
};

// 记录错误日志
const logError = (err, req) => {
  const logData = {
    message: err.message,
    statusCode: err.statusCode,
    code: err.code,
    stack: err.stack,
    method: req.method,
    url: req.originalUrl,
    ip: req.ip,
    userAgent: req.get('User-Agent'),
    requestId: req.requestId,
    userId: req.user?.id,
    body: req.body,
    params: req.params,
    query: req.query
  };
  
  if (err.statusCode >= 500) {
    logger.error('Server Error', logData);
  } else if (err.statusCode >= 400) {
    logger.warn('Client Error', logData);
  } else {
    logger.info('Error', logData);
  }
};

// 主错误处理中间件
const errorHandler = (err, req, res, next) => {
  let error = { ...err };
  error.message = err.message;
  
  // 处理不同类型的错误
  if (err.name && err.name.startsWith('Sequelize')) {
    error = handleSequelizeError(err);
  } else if (err.name && err.name.includes('JsonWebToken') || err.name === 'TokenExpiredError' || err.name === 'NotBeforeError') {
    error = handleJWTError(err);
  } else if (err.name === 'MulterError') {
    error = handleMulterError(err);
  } else if (err.name === 'MongoError' || err.name === 'MongoServerError') {
    error = handleMongoError(err);
  } else if (err.name === 'RedisError' || err.name === 'ReplyError') {
    error = handleRedisError(err);
  } else if (err.name === 'ValidationError' && err.details) {
    // Joi验证错误
    error = new ValidationError('数据验证失败', {
      fields: err.details.map(detail => ({
        field: detail.path.join('.'),
        message: detail.message,
        value: detail.context?.value
      }))
    });
  } else if (err.code === 'ENOENT') {
    error = new NotFoundError('文件未找到');
  } else if (err.code === 'EACCES') {
    error = new AppError('文件访问权限不足', 403, 'FILE_ACCESS_ERROR');
  } else if (err.code === 'EMFILE' || err.code === 'ENFILE') {
    error = new AppError('系统文件句柄不足', 503, 'FILE_HANDLE_ERROR');
  } else if (err.type === 'entity.parse.failed') {
    error = new ValidationError('请求体格式错误');
  } else if (err.type === 'entity.too.large') {
    error = new ValidationError('请求体过大');
  } else if (!err.isOperational) {
    // 未知错误，转换为通用服务器错误
    error = new AppError('服务器内部错误', 500, 'INTERNAL_ERROR');
  }
  
  // 记录错误日志
  logError(error, req);
  
  // 发送错误响应
  sendErrorResponse(error, req, res);
};

// 处理未捕获的异步错误
const asyncErrorHandler = (fn) => {
  return (req, res, next) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
};

// 404处理中间件
const notFoundHandler = (req, res, next) => {
  const error = new NotFoundError(`路由 ${req.originalUrl} 未找到`);
  next(error);
};

module.exports = {
  errorHandler,
  asyncErrorHandler,
  notFoundHandler,
  AppError,
  ValidationError,
  AuthenticationError,
  AuthorizationError,
  NotFoundError,
  ConflictError,
  RateLimitError
};